
/*
 * Copyright (C) 2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: XMLReferenceField.java 377 2010-03-11 20:50:18Z archie.cobbs $
 */

package org.dellroad.sidekar.xml;

import org.dellroad.sidekar.Item;
import org.dellroad.sidekar.ReferenceField;

/**
 * Container for a {@link ReferenceField}'s value during the Sidekar XML import/export process.
 */
class XMLReferenceField<T> extends XMLSimpleField<T> {

    private T value;
    private String entityName;
    private long id;
    private boolean isNull;

    // Used during unmarshalling
    private XMLReferenceField(XMLItem xmlItem) {
        super(xmlItem);
    }

    // Used during unmarshalling
    private XMLReferenceField(XMLField xmlField) {
        super(xmlField);
    }

    // Used during marshalling
    public XMLReferenceField(String name, T value) {
        super(name);
        this.value = value;
        Item item = (Item)value;
        if (item != null) {
            this.entityName = item.getSidekarEntity().getName();
            this.id = item.getSidekarId();
        }
        this.isNull = value == null;
    }

    // Used during unmarshalling (for elements contained in arrays and complex fields)
    @Override
    @SuppressWarnings("unchecked")
    public T getObjectValue() {
        if (!this.isNull && this.value == null && this.entityName != null)
            this.value = (T)this.xmlItem.getXMLData().getXMLDatabase().getDatabase().getEntity(this.entityName).get(this.id);
        return this.value;
    }

    // Used during unmarshalling (for elements not contained in arrays and complex fields)
    @Override
    public <E> void caseReferenceField(ReferenceField<E> field) {
        field.set(getItem(), field.cast(getObjectValue()));
    }

    // Used during unmarshalling
    public static <T> XMLReferenceField<T> newInstance(Object obj) {
        return obj instanceof XMLItem ? new XMLReferenceField<T>((XMLItem)obj) : new XMLReferenceField<T>((XMLField)obj);
    }
}

